package com.yeyaomai.dksns.flowis.quartz;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.data.mongodb.core.mapreduce.GroupByResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import com.yeyaomai.dksns.flowis.dao.DetailDao;
import com.yeyaomai.dksns.flowis.dao.MongoDBBasicDao;
import com.yeyaomai.dksns.flowis.dao.PageDao;
import com.yeyaomai.dksns.flowis.dao.ReferPageDao;
import com.yeyaomai.dksns.flowis.domain.ReferPage;
import com.yeyaomai.dksns.flowis.domain.flowisdetail.FlowisStatDetailDTO;
import com.yeyaomai.dksns.flowis.domain.flowisdetail.PageEntity;
import com.yeyaomai.dksns.flowis.util.CollectionNames;
import com.yeyaomai.dksns.flowis.util.Globals;

/**
 * author:xiaqin
 * date 2012-07-09
 * 来路页面
 */
public class ReferPageExecutor extends MongoDBBasicDao<PageEntity> {

	@Resource
	private DetailDao detailDao;
	
	@Resource
	private PageDao pageDao;

	@Resource
	private ReferPageDao referPageDao;

	final Logger logger = Logger.getLogger("quartz");
	
	/**
	 * 执行添加操作 新访客浏览次数,是指从某个页面过来的第一次访问的用户访问端口的网站的页面次数
	 * 站内总浏览数是指从某一页面过来的访问用户访问端口网站的页面次数
	 * 用于来访页面不是端口网的过来的页面的排名状况
	 * @throws ParseException
	 */
	public void saveReferPage() throws ParseException {
		Date date = new Date();
		Date dates = new Date(date.getTime() - 1 * 3600 * 1000);
		String formDate = Globals.FORMAT_TYPE_A.format(dates);
		String toDate = Globals.FORMAT_TYPE_A.format(date);
		if(formDate.equals(toDate))
		{
			toDate = Globals.FORMAT_TYPE_A.format(new Date(Globals.FORMAT_TYPE_A.parse(toDate).getTime()+1 * 24 * 3600 * 1000));
		}
		referPageDao.delReferPageByDateAndPage(formDate);
		GroupByResults<FlowisStatDetailDTO> result = this.getVisitCountByTime(formDate, toDate);
		for (FlowisStatDetailDTO engine : result) {
			if(engine.getReferer().indexOf("duankou") == -1)
			{
			String access_url = engine.getReferer();
			PageEntity page = new PageEntity();
			page.setReferDate(formDate);
			page.setPageName(access_url);
			page.setVisitCount(engine.getVisitCount());
			Integer uniqueCount = this.getUVByTime(formDate, toDate, access_url);
			page.setUniqueHost(uniqueCount);
			Integer ip = this.getIpByTime(formDate, toDate, access_url);
			page.setIp(ip);
			Integer newuniqueHost = this.getNewUVByTime(formDate, toDate,access_url);
			page.setNewUniqueHost(newuniqueHost);
			Integer newuniqueCount = this.countReferPageByTimeAndPage(formDate,
					toDate, access_url, 1);
			page.setNewUniqueHostCount(newuniqueCount);
			Integer standCount = this.countReferPageByTimeAndPage(formDate,
					toDate, access_url, 2);
			page.setStandCount(standCount);
			pageDao.insert(page);
			}
		}
		List<PageEntity> pageList = new ArrayList<PageEntity>();
		pageList = pageDao.findList();
		PageEntity page = null;
		for(int i = 0;i<pageList.size();i++)
		{
			page = pageList.get(i);
			ReferPage referPage = new ReferPage();
			referPage.setVisitCount(page.getVisitCount());
			referPage.setReferDate(Globals.FORMAT_TYPE_A.parse(page.getReferDate()));
			referPage.setPageName(page.getPageName());
			referPage.setIp(page.getIp());
			referPage.setNewUniqueHost(page.getNewUniqueHost());
			referPage.setNewUniqueHostCount(page.getNewUniqueHostCount());
			referPage.setUniqueHost(page.getUniqueHost());
			referPage.setStandCount(page.getStandCount());
			referPageDao.addReferPage(referPage);
		}
		pageDao.delPage();
		logger.info(date+"running saveReferPage Task add Data Times of the"+pageList.size());
		logger.info("#############################来路时间"+formDate+"来路页面定时任务执行添加完毕"+toDate+"######################");
	}

	/**
	 * 按页面统计访问次数
	 */ 
	private GroupByResults<FlowisStatDetailDTO> getVisitCountByTime(
			String fromTrendDay, String toTrendDay) {

		String mapFunction = "{ visitCount: 0}";
		String reduceFunction = "function(doc, prev) {prev.visitCount+=1}";
		Criteria criteria =  Criteria.where("access_date").gte(fromTrendDay).lt(toTrendDay).and("referer").ne("");
		GroupByResults<FlowisStatDetailDTO> result = detailDao.group(criteria, CollectionNames.REFERER, mapFunction, reduceFunction, FlowisStatDetailDTO.class);
		return result;
	}
	
	/**
	 * 定时任务处理UV
	 */
	private int getUVByTime(String formDate, String toDate, String page) {
		String mapFunction = "{ visitCount: 0}";
		String reduceFunction = "function(doc, prev) {prev.visitCount+=1}";
		Criteria criteria = Criteria.where("access_date").gte(formDate).lt(toDate).and("referer").is(page);
		int uvcount = detailDao.group(criteria, CollectionNames.COOKIEID, mapFunction, reduceFunction, FlowisStatDetailDTO.class).getKeys();
		return uvcount;
	}

	/**
	 * 定时任务处理IP
	 */ 
	private int getIpByTime(String formDate, String toDate, String page) {
		String mapFunction = "{ip: 0}";
		String reduceFunction = "function(doc, prev) {prev.ip+=1}";
		Criteria criteria = Criteria.where("access_date").gte(formDate).lt(toDate).and("referer").is(page);
		int ipcount = detailDao.group(criteria, CollectionNames.IP, mapFunction, reduceFunction, FlowisStatDetailDTO.class).getKeys();
		return ipcount;
	}

	/**
	 * 定时任务处理newuv
	 */
	private int getNewUVByTime(String formDate, String toDate, String page) {
		int newuvcount = 0;
		String mapFunction = "{cookieId: 0}";
		String reduceFunction = "function(doc, prev) {prev.cookieId+=1}";
		Criteria criteria = Criteria.where("access_date").gte(formDate).lt(toDate).and("referer").is(page).and("visitCount").is(1);
		newuvcount = detailDao.group(criteria, CollectionNames.COOKIEID, mapFunction, reduceFunction, FlowisStatDetailDTO.class).getKeys();
		/*for (FlowisStatDetailDTO engine : result) {
			if (engine.getVisitCount().equals(1)) {
				newuvcount = Integer
						.valueOf(engine.getCookieId().split("\\.")[0]);
			}
		}*/
		return newuvcount;
	}

	/**
	 * 按页面统计新访客浏览次数-
	 */
	private Integer countReferPageByTimeAndPage(String formDate, String toDate,
			String page, int type) {
		Query query = null;
		List<FlowisStatDetailDTO> flow = new ArrayList<FlowisStatDetailDTO>();
		if (type == 1) {

			query = new Query(Criteria.where("access_date").gte(formDate)
					.lt(toDate).and("visitCount").is(1).and("referer")
					.is(page));

		} else {
			query = new Query(Criteria.where("access_date").gte(formDate)
					.lt(toDate).and("referer").is(page));
		}
		flow = mongoTemplate.find(query, FlowisStatDetailDTO.class);
		List<String> listDomainId = new ArrayList<String>();
		for (FlowisStatDetailDTO flowisStatDetailDTO : flow) {
			listDomainId.add(flowisStatDetailDTO.getDomainId());
		}
		Query queryCount = new Query(Criteria.where("access_date")
				.gte(formDate).lt(toDate).and("domainId").in(listDomainId));
		long resultCount = mongoTemplate.count(queryCount,
				FlowisStatDetailDTO.class);
		return (int) resultCount;
	}
	
}
